<?php

namespace app\bll;

use app\validate\SiteRole as ValidateSiteRole;
use Exception;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use support\Db;
use Throwable;

class SiteRole
{

    /**
     * 获取角色
     *
     * @param integer $id
     * @param integer $siteid
     * @return array
     */
    public function find(int $id, int $siteid): array
    {
        $data =  Db::table('frame_site_role')
            ->where('id', '=', $id)
            ->where('siteid', '=', $siteid)
            ->first();

        if ($data) {
            $data = get_object_vars($data);
            $data['menus'] = Db::table('frame_site_role_menu')
                ->where('roleid', '=', $id)
                ->where('siteid', '=', $siteid)
                ->get()
                ->map(function ($value) {
                    return (array)$value;
                })
                ->toArray();

            $data['widgets'] = Db::table('frame_site_role_widget')
                ->where('roleid', '=', $id)
                ->where('siteid', '=', $siteid)
                ->get()
                ->map(function ($value) {
                    return (array)$value;
                })
                ->toArray();

            return $data;
        }
        return [];
    }


    /**
     * 根据一组角色ID 获取相对应的权限
     *
     * @param array|string $ids
     * @return array
     */
    public function selAuthByIds(array|string $ids): array
    {
        if (is_string($ids)) {
            $ids = explode(',',  $ids);
        }
        $menus = Db::table('frame_site_role_menu')
            ->leftJoin('frame_admin_menu', 'frame_admin_menu.ident', '=', 'frame_site_role_menu.ident')
            ->whereIn('frame_site_role_menu.roleid', $ids)
            ->orderBy('frame_admin_menu.sort', 'asc')
            ->distinct()
            ->get('frame_admin_menu.*')
            ->map(function ($value) {
                return (array)$value;
            })
            ->toArray();

        $widgets = Db::table('frame_site_role_widget')
            ->leftJoin('frame_component_widget', 'frame_component_widget.ident', '=', 'frame_site_role_widget.ident')
            ->whereIn('frame_site_role_widget.roleid', $ids)
            ->distinct()
            ->get('frame_component_widget.*')
            ->map(function ($value) {
                return (array)$value;
            })
            ->toArray();
        return [
            'menus' => $menus,
            'widgets' => $widgets,
        ];
    }


    /**
     * 查询角色
     *
     * @param integer $siteid
     * @return array
     */
    public function select(int $siteid = 0): array
    {
        return Db::table('frame_site_role')
            ->when($siteid != 0, function ($query) use ($siteid) {
                return $query->where('siteid', '=', $siteid);
            })
            ->get()
            ->map(function ($value) {
                return (array)$value;
            })
            ->toArray();
    }
    /**
     * 添加站点角色
     *
     * @param array $data
     * @return integer
     */
    public function add(array $data): int
    {
        $ValidateSiteRole = new ValidateSiteRole();
        if (!$ValidateSiteRole->check($data)) {
            throw new Exception($ValidateSiteRole->getSimpleError());
        }

        Db::beginTransaction();

        try {
            $roleid = Db::table('frame_site_role')
                ->insertGetId([
                    'siteid' => $data['siteid'],
                    'title' => $data['title'],
                ]);
            $menus = [];
            if (isset($data['menuidents']) && is_array($data['menuidents']) && $data['menuidents']) {

                $bllAdminMenu = new AdminMenu();
                $meenuTree = $bllAdminMenu->tree(belong: 1);

                $menuidents = [];
                foreach ($data['menuidents'] as $key => $ident) {
                    $node = $meenuTree->getNodeById($ident);
                    $ancestormenus = $bllAdminMenu->getAncestorsAndSelfByNode($node);
                    foreach ($ancestormenus as $ancestormenu) {
                        $menuidents[] = $ancestormenu['ident'];
                    }
                }
                $menuidents = array_unique($menuidents);
                foreach ($menuidents as $menuident) {
                    $menus[] = [
                        'siteid' => $data['siteid'],
                        'roleid' => $roleid,
                        'ident' => $menuident,

                    ];
                }

                if ($menus) {
                    Db::table('frame_site_role_menu')
                        ->insert($menus);
                }
            }

            $widgetidents = [];
            if (isset($data['widgetidents']) && is_array($data['widgetidents']) && $data['widgetidents']) {
                foreach ($data['widgetidents'] as $widgetident) {

                    $widgetidents[] = [
                        'siteid' => $data['siteid'],
                        'roleid' => $roleid,
                        'ident' => $widgetident,

                    ];
                }
            }

            if ($widgetidents) {
                Db::table('frame_site_role_widget')
                    ->insert($widgetidents);
            }


            Db::commit();
            return $roleid;
        } catch (Throwable $ex) {
            Db::rollBack();
            throw $ex;
        }
    }

    /**
     * 修改
     *
     * @param integer $id
     * @param integer $siteid
     * @param array $data
     * @return void
     */
    public function edit(int $id, int $siteid, array $data)
    {
        $ValidateSiteRole = new ValidateSiteRole();
        if (!$ValidateSiteRole->check($data)) {
            throw new Exception($ValidateSiteRole->getSimpleError());
        }

        Db::beginTransaction();

        try {

            Db::table('frame_site_role')
                ->where('id', '=', $id)
                ->where('siteid', '=', $siteid)
                ->update([
                    'title' => $data['title'],
                ]);
            Db::table('frame_site_role_menu')
                ->where('siteid', '=', $siteid)
                ->where('roleid', '=', $id)
                ->delete();

            Db::table('frame_site_role_widget')
                ->where('siteid', '=', $siteid)
                ->where('roleid', '=', $id)
                ->delete();


            if (isset($data['menuidents']) && is_array($data['menuidents']) && $data['menuidents']) {


                $bllAdminMenu = new AdminMenu();
                $meenuTree = $bllAdminMenu->tree(belong: 1);

                $menuidents = [];
                foreach ($data['menuidents'] as $key => $ident) {
                    $node = $meenuTree->getNodeById($ident);
                    $ancestormenus = $bllAdminMenu->getAncestorsAndSelfByNode($node);
                    foreach ($ancestormenus as $ancestormenu) {
                        $menuidents[] = $ancestormenu['ident'];
                    }
                }
                $menuidents = array_unique($menuidents);
                foreach ($menuidents as $menuident) {
                    $menus[] = [
                        'siteid' => $data['siteid'],
                        'roleid' => $id,
                        'ident' => $menuident,

                    ];
                }
                if ($menus) {
                    Db::table('frame_site_role_menu')
                        ->insert($menus);
                }
            }

            $widgetidents = [];
            if (isset($data['widgetidents']) && is_array($data['widgetidents']) && $data['widgetidents']) {
                foreach ($data['widgetidents'] as $widgetident) {

                    $widgetidents[] = [
                        'siteid' => $data['siteid'],
                        'roleid' => $id,
                        'ident' => $widgetident,

                    ];
                }
            }

            if ($widgetidents) {
                Db::table('frame_site_role_widget')
                    ->insert($widgetidents);
            }

            Db::commit();
        } catch (Throwable $ex) {
            Db::rollBack();
            throw $ex;
        }
    }


    /**
     * 删除
     *
     * @param integer $id
     * @param integer $siteid
     * @return void
     */
    public function delete(int $id, int $siteid)
    {
        Db::beginTransaction();
        try {
            Db::table('frame_site_role')
                ->where('id', '=', $id)
                ->where('siteid', '=', $siteid)
                ->delete();

            Db::table('frame_site_role_menu')
                ->where('siteid', '=', $siteid)
                ->where('roleid', '=', $id)
                ->delete();

            Db::table('frame_site_role_widget')
                ->where('siteid', '=', $siteid)
                ->where('roleid', '=', $id)
                ->delete();
            Db::commit();
        } catch (Throwable $ex) {
            Db::rollBack();
            throw $ex;
        }
    }

    /**
     * 分页查询
     *
     * @param string $name
     * @param string $ident
     * @param integer $pagesize
     * @return LengthAwarePaginator
     */
    public function paginator(
        string $title = '',
        int $siteid = 0,
        int $pagesize = 20
    ): LengthAwarePaginator {
        return  Db::table('frame_site_role')
            ->when($title !== '', function ($query) use ($title) {
                return $query->where('title', 'like', '%' . $title . '%');
            })
            ->when($siteid !== 0, function ($query) use ($siteid) {
                return $query->where('siteid', '=', $siteid);
            })
            ->orderBy('id', 'desc')
            ->paginate($pagesize);
    }
}
